package user_daos

import (
	"errors"
	"fmt"
	"gorm.io/gorm"
	"log"
	"rabbit_love/src/model"
	"rabbit_love/src/service/client/forms/request/user_forms"
	"rabbit_love/src/service/client/utils"
	"rabbit_love/src/service/client/utils/cache"
	RabbitUtils "rabbit_love/src/utils"
	"rabbit_love/src/utils/encryption"
	"rabbit_love/src/utils/local"
	"rabbit_love/src/utils/oss"
	"time"
)

func LoginDao(form *user_forms.LoginRequest) (token string, err error) {
	var (
		ClientDB = utils.ClientDB
		userData model.UserTable
	)

	if err = ClientDB.Select("passWord, id, loverRelationId").Where("userName = ? or email = ?", form.UserName, form.UserName).First(&userData).Error; err != nil {
		log.Println("LoginDao", err.Error())
		return "", errors.New("用户名或密码错误")
	}

	if !encryption.ComparePasswords(userData.PassWord, []byte(form.PassWord)) {
		return "", errors.New("用户名或密码错误")
	}

	if token, err = RabbitUtils.GetToken(int(userData.ID), int(userData.LoverRelationTableId), form.UserName); err == nil {
		return token, nil
	}
	log.Println("LoginDao", err.Error())
	return "", errors.New("用户名或密码错误")
}

func ValCodeDao(form *user_forms.RegisterValCodeRequest) error {
	var (
		models string
		code   string
		err    error
	)

	// 获取随机验证码
	code = local.GetRandomBoth(6)

	// 存储到Redis中，添加时间锁
	_, err = cache.RedisValDB.Set(form.Email, code, 10*time.Minute).Result()
	if err != nil {
		return errors.New("存储验证码失败")
	}

	if form.Type == user_forms.Register {
		models = fmt.Sprintf(
			utils.RegisterCode, code,
		)

		if err = utils.SendEmailWithPool([]string{form.Email}, "验证码", models); err != nil {
			return errors.New("邮件发送失败")
		}
	} else if form.Type == user_forms.Forget {
		models = fmt.Sprintf(utils.ForgetCode, code)
		if err = utils.SendEmailWithPool([]string{form.Email}, "忘记密码", models); err != nil {
			return errors.New("邮件发送失败")
		}
	} else {
		return errors.New("请求错误")
	}

	return nil
}

func RegisterDao(form *user_forms.RegisterRequest) (token string, err error) {
	var (
		code     string
		clientDB = utils.ClientDB
	)

	code, err = cache.RedisValDB.Get(form.Email).Result()
	if err != nil {
		return "", errors.New("请先获取验证码")
	}

	if form.Code != code {
		return "", errors.New("验证码错误")
	}

	_, _ = cache.RedisValDB.Del(form.Email).Result()

	modelData := &model.UserTable{
		NickName: form.NickName,
		Email:    form.Email,
		UserName: form.UserName,
		PassWord: encryption.HashAndSalt([]byte(form.PassWord)),
	}
	err = clientDB.Create(&modelData).Error
	if err != nil {
		return "", err
	}

	if token, err = RabbitUtils.GetToken(int(modelData.ID), 0, form.UserName); err == nil {
		return token, nil
	}

	log.Println("RegisterDao", err.Error())
	return "", err
}

/*
	TODO；
		基础信息(用户名、头像)
		if exist:
				恋人信息(起始时间、恋人信息(用户名、头像))
				新的未看到打卡信息
				新的未看的日常分享
	FLAG：
		消息信息
*/
func UserInfoDao(userId int) (map[string]interface{}, error) {
	data, err := userInfoGet(userId)
	if err != nil {
		return nil, err
	}

	return data, nil
}

func UpdateUserInfoDao(userId int, form *user_forms.UpdateUserInfoRequest) error {
	var (
		oldUserInfos model.UserTable
		clientDB     = utils.ClientDB
		err          error
	)

	if err = clientDB.Where("id = ?", userId).First(&oldUserInfos).Error; err != nil {
		return errors.New("获取用户信息失败")
	}

	if form.Pic != nil {
		if oldUserInfos.IconUrl != "" {
			oss.DelFile(oldUserInfos.IconUrl)
		}

		var filePath string
		filePath, err = oss.SaveFileToOSS(form.Pic)
		if err != nil {
			log.Println("AddDataListDao Err: ", err.Error())
			return errors.New("文件上传失败")
		}

		oldUserInfos.IconUrl = filePath
	}

	oldUserInfos.UserName = form.NickName
	oldUserInfos.Sex = string(form.Sex)
	oldUserInfos.BirthDay = time.Time(form.BirthDay)

	if err = clientDB.Model(&model.UserTable{}).Where("id = ?", userId).Updates(&oldUserInfos).Error; err != nil {
		log.Println("UpdateUserInfoDao Err: ", err.Error())
		return errors.New("更新失败, 请重试")
	}
	return nil
}

func GetNomUserInfo(userName string) (*UserInfoStruct, error) {
	var (
		userInfos UserInfoStruct
		clientDB  = utils.ClientDB
		err       error
	)

	err = clientDB.Model(&model.UserTable{}).
		Select("userName UserName, nickName NickName, iconUrl IconUrl, sex Sex, loverRelationId LoverRelationId, birthDay BirthDay").
		Where("userName = ? or email = ?", userName, userName).
		Scan(&userInfos).Error
	if err != nil {
		return nil, errors.New("没有找到对应的用户")
	}

	return &userInfos, nil
}

func SpecInviteLoverDao(userId int, userName string) error {
	var (
		clientDB = utils.ClientDB

		mineUserInfos model.UserTable

		userInfos model.UserTable
		err       error
	)

	if err = clientDB.Model(&model.UserTable{}).Select("loverRelationId, nickName, email, userName").Where("id = ?", userId).First(&mineUserInfos).Error; err != nil {
		log.Println("SpecInviteLoverDao Get UserTable Err: ", err.Error())
		return errors.New("珍惜眼前人")
	}

	if mineUserInfos.LoverRelationTableId != 0 {
		return errors.New("请不要脚踏多只船")
	}

	if mineUserInfos.UserName == userName || mineUserInfos.Email == userName {
		return errors.New("无法邀请自己")
	}

	if err = clientDB.Model(&model.UserTable{}).Select("id, loverRelationId, email").Where("userName = ? or email = ?", userName, userName).First(&userInfos).Error; err != nil {
		log.Println("SpecInviteLoverDao Get UserTable Err: ", err.Error())
		return errors.New("没有找到对应用户")
	}

	if userInfos.LoverRelationTableId != 0 {
		return errors.New("对方已有情侣")
	}

	// 邀请过，更改状态和数据
	var inviteInfo *model.LoverInviteTable = nil
	count := clientDB.Model(&model.LoverInviteTable{}).Where("`from` = ? and `to` = ? and `accept` != ?", userId, userInfos.ID, model.Allow).First(&inviteInfo).RowsAffected
	if count == 0 {
		// 没有邀请过，进行邀请
		err = clientDB.Transaction(func(tx *gorm.DB) error {
			data := &model.LoverInviteTable{
				From:   int64(userId),
				To:     userInfos.ID,
				Read:   false,
				Accept: model.None,
			}
			if err = clientDB.Create(&data).Error; err != nil {
				log.Println("SpecInviteLoverDao Create LoverInviteTable Err: ", err.Error())
				return err
			}

			/*
				获取当前被邀请为情侣的数量，进行通知
			*/
			var (
				count int64
			)
			if err = clientDB.Model(&model.LoverInviteTable{}).Where("`to` = ? and `read` = false and `accept` = ?", userInfos.ID, model.None).Count(&count).Error; err != nil {
				log.Println("SpecInviteLoverDao Count LoverInviteTable Err: ", err.Error())
				return err
			}

			dataModel := fmt.Sprintf(utils.InviteLoverNotify, mineUserInfos.NickName, count)
			_ = utils.SendEmailWithPool([]string{userInfos.Email}, "通知消息", dataModel)
			//if err != nil {
			//	log.Println("SpecInviteLoverDao Send Email Err: ", err.Error())
			//	return err
			//}

			return nil
		})
		if err != nil {
			return errors.New("邀请失败")
		}
	} else {
		inviteInfo.Accept = model.None
		inviteInfo.Read = false
		if err = clientDB.Save(&inviteInfo).Error; err != nil {
			return errors.New("邀请失败")
		}
	}
	return nil
}

func ApplyListDao(userId int64) (map[string]interface{}, error) {
	var (
		clientDB = utils.ClientDB
		fromList []map[string]interface{} // 由我发送的邀请
		toList   []map[string]interface{} // 发送给自己的邀请
		list     = make(map[string]interface{})
		err      error
	)

	err = clientDB.Transaction(func(tx *gorm.DB) error {
		if err = clientDB.Model(&model.LoverInviteTable{}).
			Select("`ut`.`userName` as `userName`, "+
				"`ut`.`nickName` as `nickName`, "+
				"`ut`.`email` as `email`, "+
				"`ut`.`iconUrl` as `iconUrl`, "+
				"`ut`.`birthDay` as `birthDay`, "+
				"`lover_invite_table`.`id` as `inviteId`, "+
				"`lover_invite_table`.`accept` as `accept`, "+
				"`lover_invite_table`.`read` as `read`").
			Joins("LEFT JOIN user_table ut on ut.id=lover_invite_table.to").
			Where("`lover_invite_table`.`from` = ?", userId).
			Scan(&fromList).Error; err != nil {
			log.Println("ApplyListDao From Err: ", err.Error())
			return err
		}

		if err = clientDB.Model(&model.LoverInviteTable{}).Where("`from` = ?", userId).Update("`read`", true).Error; err != nil {
			return err
		}

		return nil
	})
	if err != nil {
		log.Println("ApplyListDao Err: ", err.Error())
		return nil, errors.New("获取数据失败")
	}

	err = clientDB.Transaction(func(tx *gorm.DB) error {
		if err = clientDB.Model(&model.LoverInviteTable{}).
			Select("`ut`.`userName` as `userName`, "+
				"`ut`.`nickName` as `nickName`, "+
				"`ut`.`email` as `email`, "+
				"`ut`.`iconUrl` as `iconUrl`, "+
				"`ut`.`birthDay` as `birthDay`, "+
				"`lover_invite_table`.`id` as `inviteId`, "+
				"`lover_invite_table`.`accept` as `accept`, "+
				"`lover_invite_table`.`read` as `read`").
			Joins("LEFT JOIN user_table ut on ut.id=lover_invite_table.from").
			Where("`lover_invite_table`.`to` = ?", userId).
			Scan(&toList).
			Error; err != nil {
			log.Println("ApplyListDao To Err: ", err.Error())
			return err
		}

		if err = clientDB.Model(&model.LoverInviteTable{}).Where("`to` = ?", userId).Update("`read`", true).Error; err != nil {
			return err
		}

		return nil
	})
	if err != nil {
		log.Println("ApplyListDao Err: ", err.Error())
		return nil, errors.New("获取数据失败")
	}

	list["fromMine"] = fromList
	list["toThem"] = toList
	return list, nil
}

func ApplyInviteDao(userId int, forms *user_forms.ApplyInviteRequest) (string, error) {
	var (
		loverInviteData model.LoverInviteTable
		clientDB        = utils.ClientDB
		token           string
		err             error
	)

	err = clientDB.Transaction(func(tx *gorm.DB) error {
		if err = clientDB.Model(&model.LoverInviteTable{}).Where("`id` = ? and `to` = ? and `accept` = ?", forms.InviteId, userId, model.None).First(&loverInviteData).Update("accept", forms.ControlType).Error; err != nil {
			log.Println("ApplyInviteDao Err: ", err.Error())
			return errors.New("没有找到对应的消息")
		}

		if forms.ControlType == model.Allow {
			var userInfos []model.UserTable
			if err = clientDB.Model(&model.UserTable{}).Select("id, userName, nickName").Where("id in (?)", []int64{loverInviteData.From, loverInviteData.To}).Find(&userInfos).Error; err != nil {
				log.Println("ApplyInviteDao Get UserTable Err: ", err.Error())
				return errors.New("获取用户信息失败")
			}

			if len(userInfos) != 2 {
				return errors.New("对方不存在，请重试")
			}

			var (
				formNickName string
				toNickName   string
				userName     string
			)
			for _, val := range userInfos {
				if val.ID == int64(userId) {
					userName = val.UserName
					toNickName = val.NickName
				} else {
					formNickName = val.NickName
				}

			}

			data := &model.LoverRelationTable{
				LoverName: "还没有名字哦",
				StartTime: time.Now(),
				LoverNickNameTable: []model.LoverNickNameTable{
					/*
						将两个用户的别名写入
					*/
					{
						UserTableId:    loverInviteData.From,
						TargetNickName: formNickName,
					},
					{
						UserTableId:    int64(userId),
						TargetNickName: toNickName,
					},
				},
			}
			if err = clientDB.Create(&data).Error; err != nil {
				log.Println("ApplyInviteDao LoverRelationTable Err: ", err.Error())
				return errors.New("建立关系失败，请重试")
			}

			if err = clientDB.Model(&model.UserTable{}).Where("id in (?)", []int64{loverInviteData.From, loverInviteData.To}).Update("loverRelationId", data.ID).Error; err != nil {
				log.Println("ApplyInviteDao Update UserTable Err: ", err.Error())
				return errors.New("更新关系失败，请重试")
			}

			token, err = RabbitUtils.GetToken(userId, int(data.ID), userName)
			if err != nil {
				return errors.New("更新关系失败，请重试")
			}
		}

		return nil
	})
	if err != nil {
		return "", err
	}

	return "", nil
}

func UpdateLoverNameDao(loverId, userId int, name string) error {
	var (
		clientDB = utils.ClientDB
		err      error
	)

	if err = clientDB.Model(&model.LoverNickNameTable{}).Where("loverRelationId = ? and userId != ?", loverId, userId).Update("targetNickName", name).Error; err != nil {
		log.Println("UpdateLoverNameDao Err: ", err.Error())
		return errors.New("更新失败，请重试")
	}
	return nil
}

func UpdateLoverRelationInfoDao(loverId int, form *user_forms.UpdateHomeNameRequest) error {
	var (
		clientDB = utils.ClientDB
		err      error
	)

	if err = clientDB.Model(&model.LoverRelationTable{}).Where("id = ?", loverId).Updates(&model.LoverRelationTable{
		LoverName: form.Name,
		StartTime: form.StartTime,
	}).Error; err != nil {
		log.Println("UpdateLoverRelationInfoDao Err: ", err.Error())
		return errors.New("修改失败，请重试")
	}

	return nil
}
